package com.bc.commoncore.util;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.*;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.Map;

public class HttpUtil {

    // 为了应用aop拦截post和get的执行情况
    // 特意将post和get的具体实现包装到了PostAndGetImpl类中
    // 应用时，访问HttpUtil即可
    private static volatile PostAndGetImpl postAndGetImpl;
    //不应用aop的原始实现类,用于异常情况下的降级
    private static PostAndGetImpl noAopPostAndGetImpl = new PostAndGetImpl();
    private static final Logger logger = LoggerFactory.getLogger(HttpUtil.class);

    private static synchronized void createPostAndGetImpl() {
        if (postAndGetImpl == null) {
            try {
                postAndGetImpl = SpringBeanHelper.getCustomBeanByType(PostAndGetImpl.class);
            } catch (Exception e) {
                logger.error("PostAndGetImpl初始化失败" + e.getMessage());
            }
        }
    }

    private static PostAndGetImpl getPostAndGetImpl() {
        if (postAndGetImpl == null) {
            createPostAndGetImpl();
        }
        //由于dubbox变动时,可能导致暂时没有获取到springcontext,进而postAndGetImpl为null
        //此时为了保证系统可以正常运行,这里返回原生的PostAndGetImpl
        //这个原生的PostAndGetImpl只对本次请求有效,一旦springcontext恢复,就继续使用单例的PostAndGetImpl
        //原生的PostAndGetImpl和aop增强版的PostAndGetImpl区别就是无法走aop切面进行监控
        if (postAndGetImpl == null) {
            return noAopPostAndGetImpl;
        }
        return postAndGetImpl;
    }

    public static String sendGet(String url, String param) {
        return getPostAndGetImpl().sendGet(url, param, null);
    }

    public static String sendGet(String url, String param, String cookies) {
        return getPostAndGetImpl().sendGet(url, param, cookies);
    }

    /**
     * 向指定 URL 发送POST方法的请求
     *
     * @param url   发送请求的 URL
     * @param param 请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
     * @return 所代表远程资源的响应结果
     */
    public static String sendFormPost(String url, String param) {
        return getPostAndGetImpl().sendPost(url, param, "", null);
    }

    public static String sendFormPost(String url, String param, String cookies) {
        return getPostAndGetImpl().sendPost(url, param, "", cookies);
    }

    public static String sendJsonPost(String url, String param) {
        return getPostAndGetImpl().sendPost(url, param,
                "application/json;charset=utf-8", null);
    }

    public static String sendJsonPost(String url, String param, String cookies) {
        return getPostAndGetImpl().sendPost(url, param,
                "application/json;charset=utf-8", cookies);
    }

    public static void doPut(String urlStr, Object obj) {
        getPostAndGetImpl().doPut(urlStr, obj);
    }

    public static void doPut(String urlStr, Map<String, Object> paramMap) {
        getPostAndGetImpl().doPut(urlStr, paramMap);
    }

    public static String HttpPut(String postUrl,
                                 Map<String, String> postHeaders, String postEntity) {
        return getPostAndGetImpl().HttpPut(postUrl, postHeaders, postEntity);
    }

    public static void doDelete(String urlStr, Map<String, Object> paramMap) {
        getPostAndGetImpl().doDelete(urlStr, paramMap);
    }

    public static String sendMapPost(String url, Map<String, String> paramMap) {
        return getPostAndGetImpl().sendMapPost(url, paramMap);
    }

    public static String sendPostAndUpload(String urlStr, String fileName,
                                           InputStream input) {
        return getPostAndGetImpl().sendPostAndUpload(urlStr, fileName, input);
    }

    public static String sendPostAndUpload(String urlStr, Map<String, String> param, String fileName,
                                           InputStream input) {
        if (param == null) {
            return getPostAndGetImpl().sendPostAndUpload(urlStr, fileName, input);
        }
        return getPostAndGetImpl().sendPostAndUpload(urlStr, param, fileName, input);
    }

    public static String sendMapGet(String url, Map<String, Object> params) {
        return getPostAndGetImpl().sendMapGet(url, params);
    }

    public static HttpResponse doPostBusinessLicense(String host, String path, String method,
                                                     Map<String, String> headers,
                                                     Map<String, String> querys,
                                                     String body)
            throws Exception {
        return getPostAndGetImpl().doPostBusinessLicense(host, path, method,
                headers, querys, body);
    }

    public static void addCookie(HttpServletResponse response, String cName, String cValue, int maxAge) {
        Cookie cookie = new Cookie(cName, cValue);
        cookie.setPath("/");
        cookie.setMaxAge(maxAge);
        response.addCookie(cookie);
    }

    public static void removeCookie(HttpServletResponse response, String cName, String cValue, int maxAge) {
        addCookie(response, cName, null, 0);
    }

}